Contents

%%html
<style>
.slider-grip-rect {
  fill: #3b3b3b !important;
  stroke-width: 0 !important;
  filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.3));
}
</style>
import plotly.express as px
import pandas as pd
import plotly.graph_objects as go
df = pd.read_csv('datasets/vaccine_pivot.csv')

years_sorted = sorted(df['YEAR'].unique())

fig = px.scatter(df,
                 x='Polio, 3rd dose', 
                 y='Life Expectancy', 
                 animation_frame='YEAR', 
                 animation_group='Country Name',
                 size='Child Mortality per 1000 ', 
                 color='continent', 
                 hover_name='Country Name',
                 size_max=55, 
                 range_x=[0, 100], 
                 range_y=[0, 100],
                 height=550,
                 category_orders={'YEAR': years_sorted},
                 custom_data=['Country Name', 'continent', 'Child Mortality per 1000 '])

# Update the hover template for all traces
fig.update_traces(hovertemplate="<b>%{customdata[0]}</b><br>" +
                                "<b>%{customdata[1]}</b><br><br>" +
                                "Vaccination Rate: %{x}%<br>" +
                                "Life Expectancy: %{y} years<br>" +
                                "Child Mortality per 1000: %{customdata[2]}<br>" +
                                "<extra></extra>")

# Update each frame to ensure hover template is consistent
for frame in fig.frames:
    for trace in frame.data:
        trace.hovertemplate = "<b>%{customdata[0]}</b><br>" + \
                              "<b>%{customdata[1]}</b><br><br>" + \
                              "Vaccination Rate: %{x}%<br>" + \
                              "Life Expectancy: %{y} years<br>" + \
                              "Child Mortality per 1000: %{customdata[2]}<br>" + \
                              "<extra></extra>"

fig.update_layout(
    title="Life Expectancy vs Vaccination Rates<br><sup>Child mortality declines as vaccination rate increases</sup>", title_x=0.5,
    plot_bgcolor='#cff8d6',
    paper_bgcolor='#cff8d6',
    margin={'l': 110, 'b': 220, 'r': 130, 't': 100},
    xaxis=dict(title='Polio, 3rd dose vaccination rate (%)',
               gridcolor='darkgrey',
               gridwidth=1,
               zeroline=False),   
    yaxis=dict(title='Life Expectancy (years)',
               gridcolor='darkgrey',
               gridwidth=1,
               zeroline=False),
    showlegend=True,
    hovermode='closest',
    width=780,
    
    # Customize the bottom slider
    sliders=[
        {
            'active': 0,
            'yanchor': 'top',
            'xanchor': 'left',

            # Add current year display
            'currentvalue': {
                'font': {'size': 20},
                'prefix': 'Year: ',
                'visible': True,
                'xanchor': 'right'
            },
            'pad': {'b': 10, 't': 50},
            'len': 0.9,
            'x': 0.1,
            'y': 0,
            'steps': [
                {'args': [[year], {'frame': {'duration': 300, 'redraw': True}, 'mode': 'immediate'}],
                 'label': str(year),
                 'method': 'animate'} for year in years_sorted
            ],
            'transition': {'duration': 300},
            'bgcolor': '#fff', 
            'tickcolor': '#000',
        }
    ]
)

# Add caption
fig.add_annotation(x=-0.09, y=-0.89,
                   showarrow=False,
                   xref='paper', yref='paper',
                   xanchor='left', yanchor='bottom',
                   align='left',
                   text='All countries are displayed as bubbles on the graph, where a bigger bubble size corresponds to a higher child mortality.<br>' +
                   'The child mortality has a value type of deaths per 1000 children. The x-axis corresponds to the rate of the third dose of<br>' +
                   'Polio vaccinations in percentages and the y-axis to the vaccination rate of the country. Hovering over a bubble reveals<br>' 
                   'which country the bubble represents.',
      font=dict(
        size=10
      ))

fig.show()